<template>
	<div class="calendar-container">
		<section class="calendar-month" v-if="type === 'month'">
			<div class="side-bar">
				<ul>
					<li v-for="(item, index) in yearRange"
						:key="index"
						:class="[yearSelectedIndex === index && 'selected']"
						@click="yearSelectedIndex = index ;handleScrollToElement(index)"
					>{{item}}</li>
				</ul>
			</div>
			<div class="main-content">
				<div class="scroller-container" ref="scroller">
					<ul class="scroller-wrap">
						<li v-for="(item, index) in monthRange"
							:key="index"
							:ref="item.type === 'header' ? 'year_range' : `month_${item.year}_${item.month}`"
							:class="{ 'list-header': item.type === 'header',
									  'selected': (originValue.year === String(item.year)) && (originValue.month === String(item.month)),
									  'list': item.type === 'list'
									}"
							:data-select-value-year="item.type === 'list' && item.year"
							:data-select-value-month="item.type === 'list' && item.month"
							@click="item.type === 'list' && handleMonthSelected($event)"
						>
							{{item.value}}
						</li>
					</ul>
				</div>
			</div>
		</section>
		<section class="calendar-date" v-else-if="type === 'date'">
			<ul class="date-header">
				<li v-for="item in ['日', '一', '二', '三', '四', '五', '六']" :key="item" :class="[(item === '日' || item === '六') && 'light-blue']">{{item}}</li>
			</ul>
			<div class="date-container" ref="dateScroller">
				<div class="date-wrapper">
					<div class="date-list" v-for="(item, index) in dateRange" :key="index">
						<p :ref="index === dateRange.length - 1 && 'bottom'">{{`${item.replace('-', '年')}月`}}</p>
						<ul>
							<li v-for="(date, num) in getDateList(item)" :key="num"
								:class="{
									'light-blue': (num % 7 === 0) || (num % 7 === 6),
									'select-mask': datePicketType === 'single' ? (calendarDateSelectedValue === `${date.year}-${date.month}-${date.day}`) : calendarDateSelectedValue.includes(`${date.year}-${date.month}-${date.day}`),
									'select-range': showSelectRange(date),
									'disabled': date.disabled
								}"
								:data-date-year="date.year"
								:data-date-month="date.month"
								:data-date-day="date.day"
								@click="date.type !== 'blank' && !date.disabled && handleClickDate($event)"
							>{{date.value}}</li>
						</ul>
					</div>
				</div>
			</div>
		</section>
	</div>
</template>

<style lang="less" scoped>
	@import "../../less/calendar/calendar.main.less";
</style>

<script type="text/ecmascript-6">
	import fecha from 'fecha'
	import Bscroll from 'better-scroll'
	export default {
		name: 'calendar',
		props: {
			type: {
				type: String,
				default: 'date'
			},
			calendarStartTime: {
				type: [String, Number]
			},
			calendarEndTime: {
				type: [String, Number],
				default: new Date().valueOf()
			},
			calendarRange: {
				type: Array
				// default() {
				// 	if (this.type === 'date') {
				// 		return ['2017-8', '2017-9', '2017-10', '2017-11', '2017-12'];
				// 	} else {
				// 		return ['2017', '2016', '2015', '2014', '2013', '2012', '2011', '2010'];
				// 	}
				// }
			},
			calendarSelectedValue: {
				type: String
				// default: '2016-5'
			},
			datePicketType: {
				type: String,
				default: 'range' // range single range-only
			},
			disabledStep: {
				type: Number,
				default: 0
			}
		},
		data() {
			return {
				yearSelectedIndex: null,
				originValue: {},
				calendarDateSelectedValue: []
			};
		},
		computed: {
			yearRange() {
				if (this.calendarRange) {
					return this.calendarRange;
				} else if (this.calendarStartTime && this.calendarEndTime) {
					const startYear = this.formatTime(this.calendarStartTime, 'YYYY');
					const endYear = this.formatTime(this.calendarEndTime, 'YYYY');
					const yearRange = [];
					for (let i = endYear; i >= startYear; i--) {
						yearRange.push(i);
					}
					return yearRange;
				}
			},
			monthRange() {
				const startTimeMonth = this.calendarStartTime ? this.formatTime(this.calendarStartTime, 'M') : '1';
				const endTimeMonth = this.formatTime(this.calendarEndTime || new Date(), 'M');
				const range = [];
				for (let i in this.yearRange) {
					let startMonth = 1; let endMonth = 12;
					if (Number(i) === 0) {
						endMonth = endTimeMonth;
					}
					if (Number(i) === this.yearRange.length - 1) {
						startMonth = startTimeMonth;
					}
					range.push({
						type: 'header',
						value: `${this.yearRange[i]}年`,
						year: this.yearRange[i]
					});

					for (let j = endMonth; j >= startMonth; j--) {
						range.push({
							type: 'list',
							value: `${j}月`,
							year: this.yearRange[i],
							month: `${j}`
						})
					}
				}
				return range;
			},
			dateRange() {
				if (this.calendarRange) {
					return this.calendarRange;
				}

				const startTime = this.formatTime(this.calendarStartTime, 'YYYY-M');
				const endTime = this.formatTime(this.calendarEndTime || new Date(), 'YYYY-M');
				const startYear = startTime.split('-')[0];
				const startMonth = startTime.split('-')[1];
				const endYear = endTime.split('-')[0];
				const endMonth = endTime.split('-')[1];
				const range = [];
				for (let y = startYear; y <= endYear; y++) {
					let mStart = String(y) === startYear ? startMonth : '1';
					let mEnd = String(y) === endYear ? endMonth : '12';
					for (let m = mStart; m <= mEnd; m++) {
						range.push(`${y}-${m}`);
					}
				}
				return range;
			}
		},
		created() {
		},
		mounted() {
			this.$nextTick(() => {
				const { type } = this;
				if (type === 'month') {
					this._initMonth();
				} else if (type === 'date') {
					this._initDate();
				}
			});
		},
		methods: {
			formatTime(date, format) {
				return fecha.format(date, format);
			},
			getIndexFromArray(item, arr) {
				for (let i in arr) {
					if (item === arr[i]) {
						return Number(i);
					}
				}
			},
			formatCompareDate(date) {
				const dateArr = date.split('-');
				const year = dateArr[0];
				const month = dateArr[1] < 10 ? `0${dateArr[1]}` : dateArr[1];
				const day = dateArr[2] < 10 ? `0${dateArr[2]}` : dateArr[2];
				return `${year}-${month}-${day}`;
			},
			showSelectRange(date) {
				if (this.calendarDateSelectedValue.length !== 2) {
					return false;
				}

				const formatDate = `${date.year}-${date.month < 10 ? `0${date.month}` : date.month}-${date.day < 10 ? `0${date.day}` : date.day}`;
				const startDate = this.calendarDateSelectedValue[0];
				const endDate = this.calendarDateSelectedValue[1];
				const formatStartDate = this.formatCompareDate(startDate);
				const formatEndDate = this.formatCompareDate(endDate);
				if (formatDate < formatEndDate && formatDate > formatStartDate) {
					return true;
				} else {
					return false;
				}
			},
			getDateList(ym) {
				const date = fecha.parse(ym, 'YYYY-M');
				const y = ym.split('-')[0];
				const m = ym.split('-')[1];
				const week = this.formatTime(date, 'd');
				const caculateDayTime = 24 * 60 * 60 * 1000;

				const list = [];
				for (let i = 0; i < week; i++) {
					list.push({
						type: 'blank',
						value: ''
					});
				}
				let computedDate;
				if (m === '12') {
					computedDate = `${y / 1 + 1}-1`;
				} else {
					computedDate = `${y}-${(m / 1 + 1)}`;
				}
				const dRange = (fecha.parse(computedDate, 'YYYY-M') - date) / caculateDayTime;

				const todayFormat = this.formatTime(new Date(), 'YYYY-M-D');

				const disabledStartDay = this.formatTime(new Date().valueOf() - this.disabledStep * caculateDayTime, 'YYYY-M-D');

				for (let j = 1; j <= dRange; j++) {
					list.push({
						type: 'date',
						year: y,
						month: m,
						day: j,
						value: todayFormat === `${y}-${m}-${j}` ? '今天' : j,
						disabled: this.formatCompareDate(disabledStartDay) < this.formatCompareDate(`${y}-${m}-${j}`)
					});
				}
				return list;
			},
			_initMonth() {
				const height = this.$refs.scroller.getBoundingClientRect().height;
				this.$refs.scroller.style.height = `${height - 1}px`;
				this.$scroller = new Bscroll(this.$refs.scroller, {
					click: true,
					tap: true,
					probeType: 3
				});

				const refs = this.$refs.year_range;
				const fixedValue = this.$refs.scroller.getBoundingClientRect().height / 3;
				const refsY = refs.map((item) => (item.getBoundingClientRect().top - fixedValue));

				this.$scroller.on('scroll', (xy) => {
					const { y } = xy;
					let scrollIndex = 0;
					refsY.forEach((item, index) => {
						if (Math.abs(y) >= item) {
							scrollIndex = index;
						}
					})
					this.yearSelectedIndex = scrollIndex;
				});

				const { calendarSelectedValue } = this;
				let year, month;
				if (calendarSelectedValue) {
					year = calendarSelectedValue.split('-')[0];
					month = calendarSelectedValue.split('-')[1];
					this.yearSelectedIndex = this.getIndexFromArray(year, this.yearRange);
					this.originValue = {
						year, month
					};
				} else {
					this.yearSelectedIndex = 0;
					year = this.yearRange[0];
					month = this.monthRange[1].month;
					this.originValue = {
						year,
						month
					}
				}
				const el = this.$refs[`month_${year}_${month}`][0];
				this.$scroller.scrollToElement(el, 500);
			},
			handleMonthSelected(e) {
				const selectValueYear = e.target.dataset.selectValueYear;
				const selectValueMonth = e.target.dataset.selectValueMonth;
				this.originValue = {
					year: selectValueYear,
					month: selectValueMonth
				};
				const selectedValue = `${selectValueYear}-${selectValueMonth}`;
				// console.log(selectedValue);
				this.$emit('on-month-selected', selectedValue);
			},
			handleScrollToElement(index) {
				const refs = this.$refs.year_range;
				const el = refs[index];
				this.$scroller.scrollToElement(el, 500);
			},
			_initDate() {
				const height = this.$refs.dateScroller.getBoundingClientRect().height;
				this.$refs.dateScroller.style.height = `${height - 1}px`;
				this.$scroller = new Bscroll(this.$refs.dateScroller, {
					click: true,
					tap: true,
					probeType: 1
				});
				this.$scroller.scrollToElement(this.$refs.bottom[0], 500);
				CommonUtil.toast('请选择日期');
			},
			handleClickDate(e) {
				const { dateYear, dateMonth, dateDay } = e.target.dataset;
				const type = this.datePicketType;
				const formatDate = `${dateYear}-${dateMonth}-${dateDay}`;
				if (type === 'single') {
					this.calendarDateSelectedValue = formatDate;
				} else if (type === 'range' || type === 'range-only') {
					if (this.calendarDateSelectedValue.length === 0) {
						this.calendarDateSelectedValue.push(formatDate);
						CommonUtil.toast('请再选择一个日期');
					} else if (this.calendarDateSelectedValue.length === 1) {
						if (formatDate === this.calendarDateSelectedValue[0]) {
							if (this.type === 'range-only') {
								this.calendarDateSelectedValue = [];
							} else {
								this.$emit('on-date-picker', this.calendarDateSelectedValue[0]);
								return;
							}
						} else if (this.formatCompareDate(formatDate) < this.formatCompareDate(this.calendarDateSelectedValue[0])) {
							this.calendarDateSelectedValue.unshift(formatDate);
						} else {
							this.calendarDateSelectedValue.push(formatDate);
						}
					}
				}

				if (type === 'single' || this.calendarDateSelectedValue.length === 2) {
					this.$emit('on-date-picker', this.calendarDateSelectedValue);
					// console.log(this.calendarDateSelectedValue);
				}
			}
		}
	}
</script>
